local DateActExcel = require("excel.DateActivity")
local ActivityConfig = DateActExcel.activity
local DateConfig = DateActExcel.date
local ActDefine = require("activity.Define")
local ActHandlerW = require("activity.HandlerW")
local InnerDataManagerFW = require("innerdata.InnerDataManagerFW")
local InnerDataDefine = require("innerdata.Define")
local DB = require("common.DB")
local LuaMongo = _G.lua_mongo
local Config = require("Config")
local Util = require("common.Util")
local ServerCommonFW = require("serverCommon.ServerCommonFW")
local Banshu = require("common.Banshu")

DateActDataList = DateActDataList or {}
DateActList = DateActList or {}
CallBackList = CallBackList or {}
GMDAY = GMDAY or 0

function ctlActList(complexday)
    local nTodayActList = {}
    local nTitleID = 0
    local nCtn = true
    local nTimeStamp = os.time()
    local nToday = os.date("%Y%m%d", nTimeStamp)

    local nOpenDay = ServerCommonFW.getHadOpenDay()
    local nOpenTime = ServerCommonFW.getFirstOpenTime()

    for nID, nActData in pairs(DateConfig) do
        local nOpenDateStart
        if (#nActData.openDateStart) >= 3 then
            nOpenDateStart = os.time({year = nActData.openDateStart[1], month = nActData.openDateStart[2], day = nActData.openDateStart[3], hour = 0, min = 0, sec = 0})
        end
        local nOpenDateEnd
        if #(nActData.openDateEnd) >= 3 then
            nOpenDateEnd = os.time({year = nActData.openDateEnd[1], month = nActData.openDateEnd[2], day = nActData.openDateEnd[3], hour = 0, min = 0, sec = 0})
        end

        if (nActData.day == 0 or (nOpenDay > nActData.day)) and (not nOpenDateStart or nOpenTime >= nOpenDateStart)
            and (not nOpenDateEnd or nOpenTime <= nOpenDateEnd ) then
            if nCtn then
                local nStartDateTime = {year = nActData.startDate[1], month = nActData.startDate[2], day = nActData.startDate[3], hour = 0, min = 0, sec = 0}
                local nEndDateTime = {year = nActData.endDate[1], month = nActData.endDate[2], day = nActData.endDate[3], hour = 23, min = 59, sec = 59}
                local nStartTimeStamp = os.time(nStartDateTime)
                local nEndTimeStamp = os.time(nEndDateTime)
                local nEndDate = os.date("%Y%m%d", nEndTimeStamp)
                if nTimeStamp >= nStartTimeStamp and nTimeStamp <= nEndTimeStamp then
                    nTitleID = nActData.titleid
                    for k, v in ipairs(nActData.openlist) do
                        local nActConfigID = v[1]
                        if not Banshu.isbstmAct(nActConfigID) then
                        --if not nTodayActList[nActConfigID] and not onCheckActIsRunning(nActConfigID) then
                            nCtn = false
                            nTodayActList[nActConfigID] = v
                            nTodayActList[nActConfigID].startDateTime = nStartTimeStamp
                            nTodayActList[nActConfigID].sort = k
                            nTodayActList[nActConfigID].endDateTime = nEndTimeStamp
                        --end
                        end
                    end
                end
            end
        end
    end

    return nTitleID, nTodayActList
end

function onActCheck()
    local nTimeStamp = os.time()
    if DateActList._today then
        for nActConfigID, v in pairs(DateActList._today) do
            if v._configList then
                local nStartTimeStamp = v._configList.startDateTime
                local nEndTimeStamp = v._configList.endDateTime
                local nLeftTime = ((nTimeStamp + GMDAY * 86400) >= nStartTimeStamp and (nTimeStamp + GMDAY * 86400) <= nEndTimeStamp) and nEndTimeStamp - (nTimeStamp + GMDAY * 86400) or 0
                if nLeftTime > 0 then
                    if not onProcessAct(nActConfigID, nLeftTime, ActDefine.ACT_STATE_RUNNING, v._configList) then

                    end
                end

                --检查进行中的活动
                if v._running then
                    local nEndTimeStamp = v._running.actArgs.endDateTime
                    if nEndTimeStamp <= (nTimeStamp + GMDAY * 86400) then      --活动到达结束时间
                        --onEndAct(v._running.actnum)
                        onProcessAct(nActConfigID, 0, ActDefine.ACT_STATE_ENDED, v._configList)
                    end
                end
            end
        end
    end
end

function onProcessAct(actConfigID, gap, actState, actArgs)
    local nActConfigData = DateActList._today[actConfigID]

    if not nActConfigData or not gap or not actState then
        return false
    end

    if actState == ActDefine.ACT_STATE_READY then
        onSend2LActUpdate(actConfigID, actState, actArgs)
    elseif actState == ActDefine.ACT_STATE_RUNNING then
        if not onCheckActIsRunning(actConfigID) then
            local nActVersionDate = tonumber(onGetActVersion(actConfigID))
            local nStartDate = tonumber(os.date("%Y%m%d", actArgs.startDateTime))
            local nEndDate = tonumber(os.date("%Y%m%d", actArgs.endDateTime))
            if nActVersionDate < nStartDate or nActVersionDate > nEndDate then
                --if onGetActVersion(actConfigID) ~= tonumber(os.date("%Y%m%d")) then
                DateActDataList[actConfigID] = {}
                DateActDataList[actConfigID]._data = {}
                onSetActVersion(actConfigID)
                onSetActDBData(actConfigID, DateActDataList[actConfigID]._data)
            end
            DateActDataList[actConfigID] = DateActDataList[actConfigID] or {_data = {}}
            nActConfigData._running = {actConfigID = actConfigID, actArgs = actArgs}
            onCallBack(actConfigID, actState, actArgs)
            onSend2LActUpdate(actConfigID, actState, actArgs)
            --ActHandlerW.onSendBroadcast(actConfigID, actState)
            ActHandlerW.onSend2ClientDateActUpdate(actConfigID, 2, actArgs)
            return true
        else
            if not nActConfigData._running or (nActConfigData._running and nActConfigData._running.actConfigID ~= actConfigID) then
                ActHandlerW.onSend2ClientDateActUpdate(actConfigID, 2, actArgs)
            end
        end
    elseif actState == ActDefine.ACT_STATE_ENDED then
        if not nActConfigData._endList[actConfigID] then
            nActConfigData._endList[actConfigID] = {}
        end
        onCallBack(actConfigID, actState, actArgs)
        nActConfigData._running = nil
        ActHandlerW.onSend2ClientDateActUpdate(actConfigID, 2, actArgs)
        onSend2LActUpdate(actConfigID, actState, actArgs)
        DateActDataList[actConfigID]._data = nil
        saveDB(actConfigID, DateActDataList[actConfigID])
        DateActList._today[actConfigID] = nil
        --ActHandlerW.onSendBroadcast(actConfigID, actState)
        return true
    end
    return false
end

function onSend2LActUpdate(actConfigID, status, actArgs)
    local nSend2Ldata = {
        type = 4,
        data = {
            status = status,
            actConfigID = actConfigID,
            actArgs = actArgs,
        }
    }
    InnerDataManagerFW.Send2LInnerData(nil, InnerDataDefine.INNERDATA_TYPE_ACT, nSend2Ldata)
end

function onGetTodayActList()
    return DateActList._titleID, DateActList._today
end

function onGetActStatus(actConfigID, startDateTime, endDateTime)
    if DateActList._today[actConfigID] and DateActList._today[actConfigID]._running then
        return ActDefine.ACT_STATE_RUNNING
    else
        local nStartTimeStamp = startDateTime
        local nTimeStamp = os.time()
        if (nTimeStamp + (GMDAY * 86400))  < nStartTimeStamp then
            return ActDefine.ACT_STATE_READY
        else
            return ActDefine.ACT_STATE_ENDED
        end
    end
end

function onGetLeftTime(actConfigID, actArgs)
    local nActData = DateActList._today

    if not nActData then
        return 0
    end

    local nActConfigData = nActData[actConfigID]
    if nActConfigData then
        local nStatus = onGetActStatus(actConfigID, actArgs.startDateTime, actArgs.endDateTime)
        if nStatus == ActDefine.ACT_STATE_READY then
            return 0
        elseif nStatus == ActDefine.ACT_STATE_RUNNING then
            local nEndTimeStamp = actArgs.endDateTime
            local nTimeStamp = os.time()
            local nLeftTime = nEndTimeStamp - nTimeStamp - (GMDAY * 86400)
            return nLeftTime <= 0 and 0 or nLeftTime
        else
            return 0
        end
    end
end

function onGetCurActRuleID(actConfigID)
    if DateActList._today and DateActList._today[actConfigID] and DateActList._today[actConfigID]._running then
        return DateActList._today[actConfigID]._running.actArgs.ruleid
    end
end

function onCheckActIsRunning(actConfigID)
    if DateActList._today and DateActList._today[actConfigID] and DateActList._today[actConfigID]._running then
        return true
    end
end

function onDayChange(day1)
    GMDAY = day1
    onInitTodayAct()
    onActCheck()
end

function onRegisterCallBack(actConfigID, onBeginBefore, onRunning, onEnd, actArgs)
    CallBackList[actConfigID] = {[ActDefine.ACT_STATE_BEFORESTART] = onBeginBefore, [ActDefine.ACT_STATE_RUNNING] = onRunning, [ActDefine.ACT_STATE_ENDED] = onEnd, args = actArgs}
end

function onCallBack(actConfigID, status, actArgs)
    local nCallBackData = CallBackList[actConfigID]
    if nCallBackData and nCallBackData[status] then
        nCallBackData[status](actConfigID, actArgs, nCallBackData.args)
    end
end

function onSetActVersion(actConfigID)
    DateActDataList[actConfigID].version = tonumber(os.date("%Y%m%d"))
    DateActList._today[actConfigID]._configList.version = DateActDataList[actConfigID].version
end

function onGetActVersion(actConfigID)
    if not DateActDataList[actConfigID] or not DateActDataList[actConfigID].version then
        return 0
    end
    return DateActDataList[actConfigID].version
end

function getDiffDay()            --得到已开服多少天
    if init or HAD_OPEN_DAY == nil then
        if ServerOpenTime == 0 then
            HAD_OPEN_DAY = 0
            return HAD_OPEN_DAY
        end

        local nTimeStamp = os.time()
        local nToday = os.date("%Y%m%d", nTimeStamp)
        local nServerOpenDay = os.date("%Y%m%d", getFirstOpenTime())
        if nServerOpenDay > nToday then
            HAD_OPEN_DAY = 0
        else
            local nServerOpenTime = getFirstOpenTime()
            local nServerOpenDateTime = os.date("*t", nServerOpenTime)
            nServerOpenDateTime.hour = 0
            nServerOpenDateTime.min = 0
            nServerOpenDateTime.sec = 0

            local nTodayDateTime = os.date("*t", nTimeStamp)
            nTodayDateTime.hour = 0
            nTodayDateTime.min = 0
            nTodayDateTime.sec = 0

            local nTimeDiff = os.time(nTodayDateTime) - os.time(nServerOpenDateTime)
            HAD_OPEN_DAY =  math.ceil(nTimeDiff / 86400) + 1
        end
    end
    --    print("had open day ", HAD_OPEN_DAY)
    return HAD_OPEN_DAY
end

function onInitTodayAct(mustEnd, clear)
    if Config.IS_MIDDLE then
        return
    end

    local nTimeStamp = os.time()
    local nToday = os.date("%Y%m%d", nTimeStamp)

    --检查今天进行中的活动, 如果有要结束的这里要统一结束
    if DateActList._today then
        for nActConfigID, nActData in pairs(DateActList._today) do
            if nActData._running then
                --onEndAct(v._running.actnum)
                local nEndTimeStamp = nActData._running.actArgs.endDateTime
                if mustEnd or nEndTimeStamp <= (nTimeStamp + GMDAY * 86400) then      --活动到达结束时间
                    onProcessAct(nActConfigID, 0, ActDefine.ACT_STATE_ENDED, nActData)
                end
            end
        end
    end

    if clear then
        return
    end

    DateActList._today = DateActList._today or {}

    --开始初始化今日活动列表，初始化完后DateActList中将保存所有有效的活动
    local nTitleID, nTodayActList = ctlActList()
    if nTodayActList then
        DateActList._titleID = nTitleID
        for nActConfigID, nActArgs in pairs(nTodayActList) do
            local nActRuleID = nActArgs[2]
            local nActConfigExcel = ActivityConfig[nActConfigID].actNum
            local nActRuleData = DateActExcel[nActConfigExcel][nActRuleID]
            if nActRuleData then
                if not DateActList._today[nActConfigID] or DateActList._today[nActConfigID]._running == nil then
                    if not DateActList._today[nActConfigID] then
                        DateActList._today[nActConfigID] = {
                            _beginbefore = nil,             --预告中的活动
                            _running = nil,                 --运行中的活动
                            _endList = {},
                        }
                    end

                end

                local nStartTimeStamp = nActArgs.startDateTime
                local nEndTimeStamp = nActArgs.endDateTime
                DateActList._today[nActConfigID]._configList = nil
                DateActList._today[nActConfigID]._configList = {_configID = nActConfigID, version = onGetActVersion(nActConfigID), startDateTime = nStartTimeStamp, endDateTime = nEndTimeStamp, ruleid = nActRuleID, iconid = nActArgs[4], effectid = nActArgs[5], modletype = nActArgs[7], modleid = nActArgs[6], sort = nActArgs.sort}
            end
        end
    end
end

function onGetActDesc(actConfigID, actRuleID)
    local nActConfigExcel = ActivityConfig[actConfigID].actNum
    if nActConfigExcel then
        local nActRuleData = DateActExcel[nActConfigExcel][actRuleID]
        if nActRuleData then
            return nActRuleData.desc or ""
        end
    end
end

function onSetActDBData(actConfigID, actData)
    DateActDataList[actConfigID] = DateActDataList[actConfigID] or {_data = {}}
    DateActDataList[actConfigID]._data = actData
    DateActDataList[actConfigID].version = onGetActVersion(actConfigID)
    DateActDataList[actConfigID].actConfigID = actConfigID
    saveDB(actConfigID, DateActDataList[actConfigID])
end

function onGetActDBData(actConfigID)
    return DateActDataList[actConfigID] and DateActDataList[actConfigID]._data or nil
end

function saveDB(actConfigID, actData)
    LuaMongo.update(DB.db_dateact, {actConfigID = actConfigID}, actData, true)
end

initStatus = initStatus or false
function onInit(clear, day1, day2)
    if initStatus == false or clear then
        --if clear then
        --    for nType, v in pairs(DateActList) do
        --        for nActConfigID, nActData in pairs(v._configList) do
        --            for nActNum, nActArgs in pairs(nActData) do
        --                onProcessAct(nType, nActConfigID, nActNum, 0, ActDefine.ACT_STATE_ENDED, nActArgs)
        --            end
        --        end
        --        DateActList[nType] = nil
        --    end
        --end
        --initStatus = true
    end
    LuaMongo.find(DB.db_dateact)
    while true do
        local nReader = {}
        if not LuaMongo.next(nReader) then
            break
        end

        local actConfigID = nReader.actConfigID
        if actConfigID then
            DateActDataList[actConfigID] = {}
            DateActDataList[actConfigID]._data = nReader._data
            DateActDataList[actConfigID].version = nReader.version or 0
            DateActDataList[actConfigID].actConfigID = actConfigID
        end
    end
end

onInit()

